package jmind.core.redis;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import jmind.core.lang.ScoreValue;
import jmind.core.lang.shard.LoadBalance.Balance;
import jmind.redis.RedisBootstrap;
import jmind.redis.RedisCmd;

import com.alibaba.fastjson.JSON;

public class NioRedis implements Redis {
    private final RedisCmd<String, String> c;
    private final RedisBootstrap bootstarp;

    public NioRedis(String hosts, int timeout) {
        bootstarp = new RedisBootstrap(hosts, timeout);
        c = bootstarp.connectAsync();

    }

    public NioRedis(String hosts, int timeout, Balance balance) {
        bootstarp = new RedisBootstrap(hosts, timeout);
        c = bootstarp.connectAsync(balance);

    }

    public long del(String... keys) {
        return c.del(keys);
    }

    @Override
    public String set(String key, String value) {
        return c.await(c.set(key, value));
    }

    @Override
    public String get(String key) {
        return c.await(c.get(key));
    }

    public List<String> mget(String... keys) {
        return c.mget(keys);
    }

    @Override
    public Boolean exists(String key) {
        return c.await(c.exists(key));
    }

    @Override
    public String type(String key) {
        return c.await(c.type(key));
    }

    @Override
    public boolean expire(String key, int seconds) {

        return c.await(c.expire(key, seconds));
    }

    @Override
    public boolean expireAt(String key, long unixTime) {

        return c.await(c.expireat(key, unixTime));
    }

    @Override
    public Long ttl(String key) {
        return c.await(c.ttl(key));
    }

    @Override
    public Long setbit(String key, long offset, int value) {

        return c.await(c.setbit(key, offset, value));
    }

    @Override
    public Long getbit(String key, long offset) {
        return c.await(c.getbit(key, offset));
    }

    @Override
    public Long setrange(String key, long offset, String value) {
        return c.await(c.setrange(key, offset, value));
    }

    @Override
    public String getrange(String key, long start, long end) {
        return c.await(c.getrange(key, start, end));
    }

    @Override
    public String getSet(String key, String value) {

        return c.await(c.getset(key, value));
    }

    @Override
    public Long setnx(String key, String value) {

        return c.await(c.setnx(key, value));
    }

    @Override
    public String setex(String key, int seconds, String value) {

        return c.await(c.setex(key, seconds, value));
    }

    @Override
    public Long decrBy(String key, long integer) {

        return c.await(c.decrby(key, integer));
    }

    @Override
    public Long decr(String key) {

        return c.await(c.decr(key));
    }

    @Override
    public Long incrBy(String key, long integer) {

        return c.await(c.incrby(key, integer));
    }

    @Override
    public Long incr(String key) {

        return c.await(c.incr(key));
    }

    @Override
    public Long append(String key, String value) {

        return c.await(c.append(key, value));
    }

    @Override
    public String substr(String key, int start, int end) {

        return null;
    }

    @Override
    public Long hset(String key, String field, String value) {

        return c.await(c.hset(key, field, value));
    }

    @Override
    public String hget(String key, String field) {

        return c.await(c.hget(key, field));
    }

    @Override
    public Long hsetnx(String key, String field, String value) {

        return c.await(c.hsetnx(key, field, value));
    }

    @Override
    public String hmset(String key, Map<String, String> hash) {

        return c.await(c.hmset(key, hash));
    }

    @Override
    public List<String> hmget(String key, String... fields) {

        return c.await(c.hmget(key, fields));
    }

    @Override
    public Long hincrBy(String key, String field, long value) {

        return c.await(c.hincrby(key, field, value));
    }

    @Override
    public Boolean hexists(String key, String field) {

        return c.await(c.hexists(key, field));
    }

    @Override
    public Long hdel(String key, String... field) {

        return c.await(c.hdel(key, field));
    }

    @Override
    public Long hlen(String key) {

        return c.await(c.hlen(key));
    }

    @Override
    public Set<String> hkeys(String key) {

        return c.await(c.hkeys(key));
    }

    @Override
    public List<String> hvals(String key) {

        return c.await(c.hvals(key));
    }

    @Override
    public Map<String, String> hgetAll(String key) {

        return c.await(c.hgetall(key));
    }

    @Override
    public Long rpush(String key, String... values) {

        return c.await(c.rpush(key, values));
    }

    @Override
    public Long lpush(String key, String... values) {

        return c.await(c.lpush(key, values));
    }

    @Override
    public Long llen(String key) {

        return c.await(c.llen(key));
    }

    @Override
    public List<String> lrange(String key, long start, long end) {

        return c.await(c.lrange(key, start, end));
    }

    @Override
    public String ltrim(String key, long start, long end) {

        return c.await(c.ltrim(key, start, end));
    }

    @Override
    public String lindex(String key, long index) {

        return c.await(c.lindex(key, index));
    }

    @Override
    public String lset(String key, long index, String value) {

        return c.await(c.lset(key, index, value));
    }

    @Override
    public Long lrem(String key, long count, String value) {

        return c.await(c.lrem(key, count, value));
    }

    @Override
    public String lpop(String key) {

        return c.await(c.lpop(key));
    }

    @Override
    public String rpop(String key) {

        return c.await(c.rpop(key));
    }

    @Override
    public Long sadd(String key, String... member) {

        return c.await(c.sadd(key, member));
    }

    @Override
    public Set<String> smembers(String key) {

        return c.await(c.smembers(key));
    }

    @Override
    public Long srem(String key, String... member) {

        return c.await(c.srem(key, member));
    }

    @Override
    public String spop(String key) {

        return c.await(c.spop(key));
    }

    @Override
    public Long scard(String key) {

        return c.await(c.scard(key));
    }

    @Override
    public Boolean sismember(String key, String member) {

        return c.await(c.sismember(key, member));
    }

    @Override
    public String srandmember(String key) {

        return c.await(c.srandmember(key));
    }

    @Override
    public Long zadd(String key, double score, String member) {

        return c.await(c.zadd(key, score, member));
    }

    @Override
    public Long zadd(String key, Map<Double, String> scoreMembers) {

        Object[] scoresAndValues = new Object[scoreMembers.size() * 2];
        int i = 0;
        for (Entry<Double, String> entry : scoreMembers.entrySet()) {
            scoresAndValues[i++] = entry.getKey();
            scoresAndValues[i++] = entry.getValue();
        }
        return c.await(c.zadd(key, scoresAndValues));
    }

    @Override
    public Long zaddKV(String key, Map<String, Double> scoreMembers) {
        Object[] scoresAndValues = new Object[scoreMembers.size() * 2];
        int i = 0;
        for (Entry<String, Double> entry : scoreMembers.entrySet()) {
            scoresAndValues[i++] = entry.getValue();
            scoresAndValues[i++] = entry.getKey();

        }
        return c.await(c.zadd(key, scoresAndValues));
    }

    @Override
    public List<String> zrange(String key, long start, long end) {

        return c.await(c.zrange(key, start, end));
    }

    @Override
    public Long zrem(String key, String... member) {

        return c.await(c.zrem(key, member));
    }

    @Override
    public Double zincrby(String key, double score, String member) {

        return c.await(c.zincrby(key, score, member));
    }

    @Override
    public Long zrank(String key, String member) {

        return c.await(c.zrank(key, member));
    }

    @Override
    public Long zrevrank(String key, String member) {

        return c.await(c.zrevrank(key, member));
    }

    @Override
    public List<String> zrevrange(String key, long start, long end) {

        return c.await(c.zrevrange(key, start, end));
    }

    @Override
    public Long zcard(String key) {

        return c.await(c.zcard(key));
    }

    @Override
    public Double zscore(String key, String member) {

        return c.await(c.zscore(key, member));
    }

    @Override
    public List<String> sort(String key) {

        return c.await(c.sort(key));
    }

    @Override
    public Long zcount(String key, double min, double max) {

        return c.await(c.zcount(key, min, max));
    }

    @Override
    public Long zcount(String key, String min, String max) {

        return c.await(c.zcount(key, min, max));
    }

    @Override
    public List<String> zrangeByScore(String key, double min, double max) {

        return c.await(c.zrangebyscore(key, min, max));
    }

    @Override
    public List<String> zrangeByScore(String key, String min, String max) {

        return c.await(c.zrangebyscore(key, min, max));
    }

    @Override
    public List<String> zrevrangeByScore(String key, double max, double min) {

        return c.await(c.zrangebyscore(key, min, max));
    }

    @Override
    public List<String> zrangeByScore(String key, double min, double max, int offset, int count) {

        return c.await(c.zrangebyscore(key, min, max, offset, count));
    }

    @Override
    public List<String> zrangeByScore(String key, String min, String max, int offset, int count) {

        return c.await(c.zrangebyscore(key, min, max, offset, count));
    }

    @Override
    public List<String> zrevrangeByScore(String key, double max, double min, int offset, int count) {

        return c.await(c.zrevrangebyscore(key, max, min, offset, count));
    }

    @Override
    public List<String> zrevrangeByScore(String key, String max, String min, int offset, int count) {

        return c.await(c.zrevrangebyscore(key, max, min, offset, count));
    }

    @Override
    public Long zremrangeByRank(String key, long start, long end) {

        return c.await(c.zremrangebyrank(key, start, end));
    }

    @Override
    public Long zremrangeByScore(String key, double start, double end) {

        return c.await(c.zremrangebyscore(key, start, end));
    }

    @Override
    public Long linsert(String key, boolean before, String pivot, String value) {

        return c.await(c.linsert(key, before, pivot, value));
    }

    @Override
    public Long lpushx(String key, String string) {

        return c.await(c.lpush(key, string));
    }

    @Override
    public Long rpushx(String key, String string) {

        return c.await(c.rpushx(key, string));
    }

    @Override
    public Object getResource() {

        return c;
    }

    @Override
    public void releaseResource() {
        bootstarp.shutdown();
    }

    /**
     * 利用json 把对象解析成字符串
     */
    @Override
    public boolean setObject(String key, Object o) {
        String value = JSON.toJSONString(o);
        String s = set(key, value);
        return "OK".equalsIgnoreCase(s);
    }

    public <T> T getObject(String key, Class<T> clazz) {
        String s = get(key);
        return JSON.parseObject(s, clazz);
    }

    @Override
    public List<ScoreValue<String>> zrangeWithScores(String key, long start, long end) {

        return c.await(c.zrangeWithScores(key, start, end));
    }

    @Override
    public List<ScoreValue<String>> zrevrangeWithScores(String key, long start, long end) {

        return c.await(c.zrevrangeWithScores(key, start, end));
    }

    @Override
    public List<ScoreValue<String>> zrangeByScoreWithScores(String key, double min, double max) {

        return c.await(c.zrangebyscoreWithScores(key, min, max));
    }

    @Override
    public List<ScoreValue<String>> zrevrangeByScoreWithScores(String key, double max, double min) {

        return c.await(c.zrevrangebyscoreWithScores(key, max, min));
    }

    @Override
    public List<ScoreValue<String>> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) {

        return c.await(c.zrangebyscoreWithScores(key, min, max, offset, count));
    }

    @Override
    public List<ScoreValue<String>> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) {
        return c.await(c.zrangebyscoreWithScores(key, min, max, offset, count));
    }

    @Override
    public List<String> lrevrange(String key, long start, long end) {
        long s = end + 1;
        long e = start + 1;
        return this.lrange(key, -s, -e);
    }

    @Override
    public void close(Object resource) {

    }

}
